package com.zeji.androidadvance.activity.lottie;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.content.Context;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.View;

import com.airbnb.lottie.FontAssetDelegate;
import com.airbnb.lottie.LottieAnimationView;
import com.zeji.androidadvance.utils.RxUtil;

import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;

public class EnvelopeView extends LottieAnimationView {
    private static final String AnimJson = "{\"v\": \"5.7.1\",\"fr\": 50,\"ip\": 0,\"op\": 100,\"w\": 375,\"h\": 375,\"nm\": \"信封 2\",\"ddd\": 0,\"assets\": [{\"id\": \"image_0\",\"w\": 52,\"h\": 57,\"u\": \"\",\"p\": \"\",\"e\": 1},{\"id\": \"image_1\",\"w\": 376,\"h\": 376,\"u\": \"\",\"p\": \"\",\"e\": 1},{\"id\": \"image_2\",\"w\": 268,\"h\": 264,\"u\": \"\",\"p\": \"\",\"e\": 1},{\"id\": \"image_3\",\"w\": 376,\"h\": 376,\"u\": \"\",\"p\": \"\",\"e\": 1},{\"id\": \"image_4\",\"w\": 285,\"h\": 124,\"u\": \"\",\"p\": \"\",\"e\": 1},{\"id\": \"comp_0\",\"layers\": [{\"ddd\": 0,\"ind\": 1,\"ty\": 5,\"nm\": \"txt_input\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 1,\"k\": [{\"i\": {\"x\": [0.833],\"y\": [0.833]},\"o\": {\"x\": [0.167],\"y\": [0.167]},\"t\": 50,\"s\": [100]},{\"t\": 55,\"s\": [0]}],\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 0,\"k\": [102.254,138.129,0],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [0,-53.371,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,100,100],\"ix\": 6}},\"ao\": 0,\"t\": {\"d\": {\"k\": [{\"s\": {\"sz\": [167.5,129],\"ps\": [0,-64.5],\"s\": 12,\"f\": \"PingFangSC-Regular\",\"t\": \"为了中华民族崛起而读书为了中华民族崛起而读书为了中华民族崛起而读书为了中华民族崛起而读书为了中华民族崛起而读书为了中华民族崛起而读书为了中华民族崛起而读书为了中华民族崛起而读书为了中华民族崛起而读书\",\"j\": 3,\"tr\": 0,\"lh\": 24.4,\"ls\": 0,\"fc\": [0.424,0.424,0.424]},\"t\": 0}]},\"p\": {},\"m\": {\"g\": 1,\"a\": {\"a\": 0,\"k\": [0,0],\"ix\": 2}},\"a\": []},\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0},{\"ddd\": 0,\"ind\": 2,\"ty\": 5,\"nm\": \"txt_To\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 1,\"k\": [{\"i\": {\"x\": [0.833],\"y\": [0.833]},\"o\": {\"x\": [0.167],\"y\": [0.167]},\"t\": 50,\"s\": [100]},{\"t\": 55,\"s\": [0]}],\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 0,\"k\": [102.5,113,0],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [0,0,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,100,100],\"ix\": 6}},\"ao\": 0,\"t\": {\"d\": {\"k\": [{\"s\": {\"s\": 12,\"f\": \"PingFangSC-Medium\",\"t\": \"$targetTag\",\"j\": 0,\"tr\": 0,\"lh\": 14.4,\"ls\": 0,\"fc\": [0.102,0.102,0.102]},\"t\": 0}]},\"p\": {},\"m\": {\"g\": 1,\"a\": {\"a\": 0,\"k\": [0,0],\"ix\": 2}},\"a\": []},\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0}]}],\"fonts\": {\"list\": [{\"origin\": 0,\"fPath\": \"\",\"fClass\": \"\",\"fFamily\": \"PingFang SC\",\"fWeight\": \"\",\"fStyle\": \"Medium\",\"fName\": \"PingFangSC-Medium\",\"ascent\": 72.7996826171875},{\"origin\": 0,\"fPath\": \"\",\"fClass\": \"\",\"fFamily\": \"PingFang SC\",\"fWeight\": \"\",\"fStyle\": \"Regular\",\"fName\": \"PingFangSC-Regular\",\"ascent\": 72.7996826171875}]},\"layers\": [{\"ddd\": 0,\"ind\": 1,\"ty\": 2,\"nm\": \"邮戳\",\"refId\": \"image_0\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 0,\"k\": 100,\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 1,\"k\": [{\"i\": {\"x\": 0.667,\"y\": 1},\"o\": {\"x\": 0.333,\"y\": 0},\"t\": 50,\"s\": [187.5,254.5,0],\"to\": [0,1.667,0],\"ti\": [0,0,0]},{\"i\": {\"x\": 0.667,\"y\": 1},\"o\": {\"x\": 0.333,\"y\": 0},\"t\": 65,\"s\": [187.5,264.5,0],\"to\": [0,0,0],\"ti\": [0,1.667,0]},{\"t\": 80,\"s\": [187.5,254.5,0]}],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [26,28.5,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,100,100],\"ix\": 6}},\"ao\": 0,\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0},{\"ddd\": 0,\"ind\": 2,\"ty\": 5,\"nm\": \"txt_From\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 0,\"k\": 100,\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 0,\"k\": [292.893,323.851,0],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [0,0,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,100,100],\"ix\": 6}},\"ao\": 0,\"t\": {\"d\": {\"k\": [{\"s\": {\"s\": 12,\"f\": \"PingFangSC-Regular\",\"t\": \"$fromTag\",\"j\": 1,\"tr\": 0,\"lh\": 14.4,\"ls\": 0,\"fc\": [0.616,0.616,0.616]},\"t\": 0}]},\"p\": {},\"m\": {\"g\": 1,\"a\": {\"a\": 0,\"k\": [0,0],\"ix\": 2}},\"a\": []},\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0},{\"ddd\": 0,\"ind\": 3,\"ty\": 2,\"nm\": \"信封\",\"refId\": \"image_1\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 0,\"k\": 100,\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 0,\"k\": [187.5,187.5,0],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [188,188,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,100,100],\"ix\": 6}},\"ao\": 0,\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0},{\"ddd\": 0,\"ind\": 4,\"ty\": 0,\"nm\": \"文本区\",\"parent\": 5,\"refId\": \"comp_0\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 0,\"k\": 100,\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 0,\"k\": [134,132,0],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [187.5,187.5,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,100,100],\"ix\": 6}},\"ao\": 0,\"w\": 375,\"h\": 375,\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0},{\"ddd\": 0,\"ind\": 5,\"ty\": 2,\"nm\": \"信纸\",\"refId\": \"image_2\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 1,\"k\": [{\"i\": {\"x\": [0.833],\"y\": [0.833]},\"o\": {\"x\": [0.167],\"y\": [0.167]},\"t\": 50,\"s\": [100]},{\"t\": 55,\"s\": [0]}],\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 1,\"k\": [{\"i\": {\"x\": 0.667,\"y\": 1},\"o\": {\"x\": 0.333,\"y\": 0},\"t\": 0,\"s\": [187.5,187.5,0],\"to\": [0,2.249,0],\"ti\": [0,-5.376,0]},{\"i\": {\"x\": 0.667,\"y\": 1},\"o\": {\"x\": 0.333,\"y\": 0},\"t\": 20,\"s\": [187.5,182,0],\"to\": [0,9.364,0],\"ti\": [0,-3.917,0]},{\"t\": 50,\"s\": [187.5,224.5,0]}],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [134,132,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,100,100],\"ix\": 6}},\"ao\": 0,\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0},{\"ddd\": 0,\"ind\": 6,\"ty\": 2,\"nm\": \"信封盖 2\",\"refId\": \"image_3\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 0,\"k\": 100,\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 1,\"k\": [{\"i\": {\"x\": 0.833,\"y\": 0.833},\"o\": {\"x\": 0.167,\"y\": 0.167},\"t\": 0,\"s\": [187.5,152.625,0],\"to\": [0,0,0],\"ti\": [0,0,0]},{\"t\": 53,\"s\": [187.5,152.625,0]}],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [188,153.125,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,-100,100],\"ix\": 6}},\"ao\": 0,\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0},{\"ddd\": 0,\"ind\": 7,\"ty\": 2,\"nm\": \"信封盖\",\"refId\": \"image_3\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 1,\"k\": [{\"i\": {\"x\": [0.667],\"y\": [1]},\"o\": {\"x\": [0.333],\"y\": [0]},\"t\": 50,\"s\": [100]},{\"t\": 65,\"s\": [0]}],\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 0,\"k\": [187.5,152.625,0],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [188,153.125,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [100,100,100],\"ix\": 6}},\"ao\": 0,\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0},{\"ddd\": 0,\"ind\": 8,\"ty\": 2,\"nm\": \"信封底\",\"refId\": \"image_4\",\"sr\": 1,\"ks\": {\"o\": {\"a\": 0,\"k\": 100,\"ix\": 11},\"r\": {\"a\": 0,\"k\": 0,\"ix\": 10},\"p\": {\"a\": 0,\"k\": [188,217.438,0],\"ix\": 2},\"a\": {\"a\": 0,\"k\": [142.5,62,0],\"ix\": 1},\"s\": {\"a\": 0,\"k\": [99.474,100,100],\"ix\": 6}},\"ao\": 0,\"ip\": 0,\"op\": 100,\"st\": 0,\"bm\": 0}],\"markers\": []}";
    // 移动动画总时间
    private static final int MOVE_TIME = 1000;
    // 移动动画帧间隔
    private static final int MOVE_FRAME_TIME = 10;
    // 移动动画终点处缩放比例
    private static final float MOVE_END_SCALE = 0.25f;
    // 移动动画总旋转角度
    private static final int MOVE_ROTATE_RADIUS = 330;

    private WeakReference<View> target;
    private Disposable moveDisposable;
    private AnimatorSet moveAnimatorSet;

    public EnvelopeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
        setOnClickListener(v -> playAnimation());
        addAnimatorListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                moveToTarget();
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

    private void moveToTarget() {
        RxUtil.dispose(moveDisposable);
        if (target == null || target.get() == null) {
            return;
        }
        View targetView = target.get();
        PointF p0 = getCenterPoint(this);
        PointF p2 = getCenterPoint(targetView);
        PointF p1 = calcControlPoint(p0, p2);
        // 记录当前中心点
        PointF nowPos = new PointF(p0);
        moveDisposable = Observable.interval(MOVE_FRAME_TIME, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .map(time -> time * MOVE_FRAME_TIME)
                .subscribe(time -> {
                    if (time > MOVE_TIME) {
                        setVisibility(View.GONE);
                        RxUtil.dispose(moveDisposable);
                        return;
                    }
                    // 当前动画进度
                    float percent = ((float) time) / MOVE_TIME;
                    // 计算当前应该所处的坐标
                    float cx = calcNowPos(p0.x, p1.x, p2.x, percent);
                    float cy = calcNowPos(p0.y, p1.y, p2.y, percent);
                    // 计算偏移量
                    int ox = (int) (cx - nowPos.x);
                    int oy = (int) (cy - nowPos.y);
                    // 移动轨迹

                    offsetLeftAndRight(ox);
                    offsetTopAndBottom(oy);
                    nowPos.offset(ox, oy);
                });
        startMoveAnim();
    }

    private void startMoveAnim() {
        animate().rotation(330f)
                .scaleX(0.15f)
                .scaleY(0.15f)
                .alpha(0.4f)
                .setDuration(MOVE_TIME)
                .start();
    }

    /**
     * 计算当前坐标点
     * @param p0 起点
     * @param p1 控制点
     * @param p2 终点
     * @param t 运动比例 0 ~ 1
     * @return 当前点
     */
    private float calcNowPos(float p0, float p1, float p2, float t) {
        float p01 = (p1 - p0) * t + p0;
        float p12 = (p2 - p1) * t + p1;
        return (p12 - p01) * t + p01;
    }

    /**
     * 计算贝塞尔曲线控制点坐标
     * @param p0 起点
     * @param p2 终点
     * @return 控制点
     */
    private PointF calcControlPoint(PointF p0, PointF p2) {
        // 中点坐标
        PointF pCenter = new PointF(
                (p0.x + p2.x) / 2,
                (p0.y + p2.y) / 2
        );
        float h02 = p2.y - p0.y;
        float w02 = p2.x - p0.x;
        // p0 ~ p2 的距离
        double dis02 = Math.sqrt((h02 * h02) + (w02 * w02));
        // sin 值
        double sin = Math.sin(h02 / dis02);
        // cos 值
        double cos = Math.cos(w02 / dis02);
        // 控制点到终点的距离
        double disCon2Cen = dis02 / 3;
        // 控制点 到 中点 的 x 偏移
        double offsetX = disCon2Cen * sin;
        // 控制点 到 中点 的 y 偏移
        double offsetY = disCon2Cen * cos;
        return new PointF(
                pCenter.x + ((float) offsetX),
                pCenter.y - ((float) offsetY)
        );
    }

    private PointF getCenterPoint(View view) {
        return new PointF(
                view.getX() + ((float) view.getWidth()) / 2,
                view.getY() + ((float) view.getHeight()) / 2
        );
    }

    private void initView() {
        setFontAssetDelegate(new FontAssetDelegate() {
            @Override
            public String getFontPath(String fontFamily) {
                return "font/ky_font_app.ttf";
            }
        });

        setAnimationFromJson(AnimJson, EnvelopeView.class.getSimpleName());
    }

    public void setTarget(View target) {
        this.target = new WeakReference<>(target);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        RxUtil.dispose(moveDisposable);
        if (moveAnimatorSet != null) {
            moveAnimatorSet.cancel();
        }
    }
}
